package com.ctsi.commons.util.async;

import com.ctsi.commons.util.UtilValidate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.*;

/**
 * 异步执行入口
 * 
 * @author yueming
 * 
 */
public class TaskManagerHolder {

	private static final Logger log = LoggerFactory.getLogger(TaskManagerHolder.class);

	private static final Map<String, ExecutorService> fixedService = new ConcurrentHashMap<String, ExecutorService>();
	private final static TaskManager tm = new TaskManager();
	private static int globalMin = 3;

	public int getGlobalMin() {
		return globalMin;
	}

	public void setGlobalMin(int globalMin) {
		TaskManagerHolder.globalMin = globalMin;
	}

	public static ExecutorService getExecutorService(String name) {
		return fixedService.get(name);
	}

	public static ExecutorService getExecutorService(int minSize, int maximumPoolSize, String name, int waitTaskSize) {
		return getExecutorService(minSize, maximumPoolSize, name, waitTaskSize, null);
	}

	private static final String  global_Name="GLOBAL_RUN";
	public static void initialize() {
		if (!fixedService.containsKey(global_Name)) {
			ExecutorService GLOBAL_RUN = new ThreadPoolExecutor(globalMin, Integer.MAX_VALUE, 2, TimeUnit.MINUTES, new SynchronousQueue<Runnable>(), PoolThreadFactory.getPoolThreadFactory(global_Name, true));
			fixedService.put(global_Name, GLOBAL_RUN);
			log.info("create GLOBAL_RUN thread min {} ", globalMin);
		} else {
			log.warn("already initialize");
		}
		tm.enableDelayTask();
	}

	public static ExecutorService get_GLOBAL_RUN() {

		return getExecutorService(globalMin, Integer.MAX_VALUE, global_Name, 0, null);

	}

	// 第一个
	public static ExecutorService getExecutorService(final int minSize,final  int maximumPoolSize, String name,final  int waitTaskSize, ThreadFactory tf) {
		String key;
		if (UtilValidate.isEmpty(name)) {
			key = minSize + "_" + maximumPoolSize;
			name = "getExecutorService";
		} else {
			key = name;
		}
		ExecutorService result;

		result = fixedService.get(key);

		if (result == null) {
			synchronized (TaskManagerHolder.class) {
				result = fixedService.get(key);
				if (result == null) {
					BlockingQueue<Runnable> bq = getBlockingQueue(waitTaskSize, Runnable.class);
					result = new ThreadPoolExecutor(minSize, maximumPoolSize, 5L, TimeUnit.MINUTES, bq, tf == null ? PoolThreadFactory.getPoolThreadFactory(name, true) : tf, new NewThreadRunsPolicy());

					fixedService.put(key, result);
					log.info("create thread pool :{} core size:{} maxSize:{}", key, minSize, maximumPoolSize);
				}

			}

		}

		return result;
	}

	public static final <T> BlockingQueue<T> getBlockingQueue(final int waitTaskSize, Class<T> clazz) {
		BlockingQueue<T> bq;
		if (waitTaskSize < 0) {
			bq = new LinkedBlockingQueue<T>();
		} else if (waitTaskSize == 0) {
			bq = new SynchronousQueue<T>();
		} else {
			bq = new ArrayBlockingQueue<T>(waitTaskSize);
		}
		return bq;
	}

	public void close() {

		log.info("close TaskManager");
		tm.terminateDelayTask();

		log.info("close fixedService");
		synchronized (TaskManagerHolder.class) {

			for (ExecutorService tem : fixedService.values()) {
				if (!tem.isShutdown())
					tem.shutdown();
			}

		}
		fixedService.clear();

	}

	

	public static TaskManager getTaskManager() {

		return tm;
	}

}
